	
void stampa(carta* c){
	if(c == NULL) return;
	printf("%d ", c->num);
	stampa(c->succ);
	return;
}


int lunghezza(carta* m){
	if(m == NULL) return 0;
	else return 1 + lunghezza(m->succ);
}


carta* precedente(carta* mazzo, carta* c){
	if(mazzo == NULL || mazzo == c) return NULL;
	if(mazzo->succ == c) return mazzo;
	else return precedente(mazzo->succ, c);
}


carta* scambia(carta* mazzo, carta* c1, carta* c2){
	if(mazzo == NULL) return NULL;
	if(c1 == c2) return mazzo;
	carta* prec1 = precedente(mazzo, c1);
	carta* prec2 = precedente(mazzo, c2);
	//se sono attaccati
	if(c1->succ == c2){
		c1->succ = c2->succ;
		c2->succ = c1;
		if(prec1 == NULL) return c2; 	//se c1 era il primo
		else {							//se non lo era
			prec1->succ = c2;
			return mazzo;	
		}
	}
	if(c2->succ == c1){
		c2->succ = c1->succ;
		c1->succ = c2;
		if(prec2 == NULL) return c1; 	//se c2 era il primo
		else {							//se non lo era
			prec2->succ = c1;
			return mazzo;	
		}
	}
	//se non sono attaccati
	carta* succ1 = c1->succ;
	carta* succ2 = c2->succ;
	if(c1 == mazzo){ //il primo è c1
		c2->succ = succ1;
		prec2->succ = c1;
		c1->succ = succ2;
		return c2;
	}
	if(c2 == mazzo){ //il primo è c2
		c1->succ = succ2;
		prec1->succ = c2;
		c2->succ = succ1;
		return c1;
	}
	//non c'è il primo in {c1, c2}
	c2->succ = succ1;
	prec2->succ = c1;
	c1->succ = succ2;
	prec1->succ = c2;
	return mazzo;
}


carta* lista_carte_togli(carta* mazzo, carta* c){
	if(mazzo == NULL) return NULL;
	if(c == NULL) return mazzo;
	if(mazzo == c) {
		carta* new_mazzo = mazzo->succ;
		c->succ = NULL;
		return new_mazzo;
	}
	carta* prec = precedente(mazzo, c);
	prec->succ = c->succ;
	c->succ = NULL;
	return mazzo; 
}


carta* mescola_mazzo(carta* mazzo){
	if(mazzo == NULL || lunghezza(mazzo) == 1) return mazzo;
	int lung = lunghezza(mazzo);
	int i = rand() % lung;			
	carta* puntatore;
	puntatore = mazzo;
	while(i > 0){
		puntatore = puntatore->succ;
		i--;
	}
	mazzo = scambia(mazzo, mazzo, puntatore); //scambio la prima con la i-esima
	lung = lunghezza(mazzo);
	mazzo->succ = mescola_mazzo(mazzo->succ);
	return mazzo;
}


carta* la_prima_di_era(carta* mazzo, int n){
	if(mazzo->era == n) return mazzo;
	else return la_prima_di_era(mazzo->succ, n);
}

carta* lista_carte_aggiungi(carta* lista, carta* da_aggiungere){
	if (da_aggiungere == NULL) return lista;
	da_aggiungere->succ = lista;
	return da_aggiungere;
}

carta* pesca7(carta** mazzo) { // mazzo è doppio puntatore
	assert(mazzo != NULL);
	int i;
	carta *mano, *curr;
	mano = *mazzo;
	curr = *mazzo;
	for(i = 0; i < 6; i++) {
		curr = curr->succ;
		assert(curr != NULL); // se è NULL significa che il mazzo ha finito le carte
	}
	*mazzo = curr->succ;
	curr->succ = NULL;
	return mano;
}

void azzera_risorse(risorse p){
	int i; 
	for(i = 0; i < 8; i++){
		p[i] = 0;
	}
	return;
}

void lista_risorse_aggiungi_ciascuno(carta* da_aggiungere, lista_risorse* lista_ereditata, int n){
	if(lista_ereditata == NULL) return;
	if(n == -1){ 	//aggiungo tutte
		int i;
		for(i = 0; i < 8; i++){
			lista_ereditata->valore[i] += da_aggiungere->produzione[i];
		}
	}
	else{			//ne aggiungo solo una
		lista_ereditata->valore[n] += da_aggiungere->produzione[n];
	}
	lista_risorse_aggiungi_ciascuno(da_aggiungere, lista_ereditata->succ, n);
}

void lista_risorse_aggiungi_ciascuno_risorse(lista_risorse* da_aggiungere, lista_risorse* lista_ereditata, int n) {
	if (lista_ereditata == NULL) return;
	assert(da_aggiungere != NULL);
	
	if (n == -1){ 	//aggiungo tutte
		int i;
		for(i = 0; i < 8; i++){
			lista_ereditata->valore[i] += da_aggiungere->valore[i];
		}
	}
	else{			//ne aggiungo solo una
		lista_ereditata->valore[n] += da_aggiungere->valore[n];
	}
	lista_risorse_aggiungi_ciascuno_risorse(da_aggiungere, lista_ereditata->succ, n);
}

lista_risorse* lista_risorse_duplica(lista_risorse* lista_ereditata){
	if(lista_ereditata == NULL) return NULL;
	lista_risorse *nuova_lista = malloc(sizeof(lista_risorse));
	assert(nuova_lista != NULL);
	int i;
	for(i = 0; i < 8; i++){
		nuova_lista->valore[i] = lista_ereditata->valore[i];
	}
	nuova_lista->succ = lista_risorse_duplica(lista_ereditata->succ);
	return nuova_lista;
}

void dealloca_lista_risorse(lista_risorse* r){
	if(r == NULL) return;
	dealloca_lista_risorse(r->succ);
	free(r);
	return;
}

lista_risorse* lista_risorse_append(lista_risorse* lista, lista_risorse* da_aggiungere){
	if(lista == NULL) return da_aggiungere;
	lista->succ = lista_risorse_append(lista->succ, da_aggiungere);
	return lista;
}

int risorse_uguali(lista_risorse* r, lista_risorse* s){
	int i; 
	for(i = 0; i < 8; i++){
		if(r->valore[i] != s->valore[i]) 	return 0;
	}
	return 1;
}

int lista_risorse_permette_di_giocare(lista_risorse* possibili_risorse, carta* da_giocare) {
	int i;
	if (possibili_risorse == NULL) {
		// controlla se la carta da giocare non richiede risorse
		for (i = 0; i < 8; i++){
			if (da_giocare->costo[i] > 0) {
				return 0;
			}
		}
		return 1;
	}
	assert(da_giocare != NULL);
	
	for (i = 0; i < 8; i++){
		if (da_giocare->costo[i] > possibili_risorse->valore[i]) {
			// con questa costo_risorse è più grande, cerca nella prossima
			return lista_risorse_permette_di_giocare(possibili_risorse->succ, da_giocare);
		}
	}
	
	return 1;
}

lista_risorse* lista_risorse_elimina_per_valore(lista_risorse* r, lista_risorse* delete){
	if(r == NULL) return NULL;
	if(risorse_uguali(r, delete)) {
		lista_risorse *succ = r->succ;
		free(r);
		return lista_risorse_elimina_per_valore(succ, delete);
	}
	r->succ = lista_risorse_elimina_per_valore(r->succ, delete);
	return r;
}

lista_risorse* lista_risorse_elimina_doppioni(lista_risorse* r){
	if (r == NULL) return NULL;
	r->succ = lista_risorse_elimina_per_valore(r->succ, r);
	r->succ = lista_risorse_elimina_doppioni(r->succ);
	return r;
}

void lista_risorse_stampa(lista_risorse* proprie) {
	if (!proprie) return;
	int i;
	for (i=0; i<8; i++) {
		printf(" %d ", proprie->valore[i]);
	}
	printf("\n");
	lista_risorse_stampa(proprie->succ);
}


carta* lista_carte_cerca_per_nome(carta* da_cercare, carta* dove_cercare){
	if(dove_cercare == NULL) return NULL;
	if(strcmp(dove_cercare->nome, da_cercare->nome)) return dove_cercare;
	else return lista_carte_cerca_per_nome(da_cercare, dove_cercare->succ);
}
